package post

import (
	"context"
	// "fmt"
	"strconv"
	"strings"

	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/logic/forum/util"
	"mall/service/backend/api/internal/logic/utils"
	"mall/service/backend/api/internal/logic/utils/parse"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/common/i18n"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/rpc/forumclient"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetPostListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetPostListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPostListLogic {
	return &GetPostListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetPostListLogic) GetPostList(req *types.ForumPostListReq) (*types.ForumPostListResp, error) {
	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	if req.Diagnose != nil && *req.Diagnose == 1 {
		data, err := l.svcCtx.ForumRpc.DiagnosePostToEs(l.ctx, &forumclient.BackendPostListReq{
			Page:     page,
			PageSize: pageSize,
		})
		if err != nil {
			return nil, err
		}

		return &types.ForumPostListResp{
			BaseDataInfo: types.BaseDataInfo{
				Success: true,
				Msg:     l.svcCtx.Trans.Trans(l.ctx, i18n.Success),
			},
			Data: types.ForumPostListInfo{
				BaseListInfo: types.BaseListInfo{
					Current:  page,
					PageSize: pageSize,
					Total:    data.GetTotal(),
				},
			},
		}, nil
	}

	orderBys := util.ParseSorterNew(req.Sorter)
	filterBys := util.ParseFilterNew(req.Filter, req.Type)

	var ids string
	var title *string
	if req.Search != nil && len(strings.TrimSpace(*req.Search)) > 0 { // 前端可以搜名称或者ID
		reqSearch := strings.TrimSpace(*req.Search)
		if _, err := strconv.ParseInt(reqSearch, 10, 64); err == nil {
			ids = reqSearch
		} else {
			title = pointy.GetPointer(reqSearch)
		}
	}
	if req.Title != nil && len(strings.TrimSpace(*req.Title)) > 0 {
		title = pointy.GetPointer(strings.TrimSpace(*req.Title))
	}
	var excerpt *string
	if req.Excerpt != nil && len(strings.TrimSpace(*req.Excerpt)) > 0 {
		excerpt = pointy.GetPointer(strings.TrimSpace(*req.Excerpt))
	}

	if req.Id != nil && *req.Id > 0 {
		ids = strconv.FormatInt(int64(*req.Id), 10)
	}
	if req.PostIds != nil && len(strings.TrimSpace(*req.PostIds)) > 0 {
		ids = strings.TrimSpace(*req.PostIds)
	}

	data, err := l.svcCtx.ForumRpc.BackendGetPostList(l.ctx, &forumclient.BackendPostListReq{
		Page:        page,
		PageSize:    pageSize,
		Ids:         pointy.GetPointer(ids),
		Title:       title,
		Excerpt:     excerpt,
		ForumId:     req.ForumId,
		AuthorId:    req.AuthorId,
		ParentId:    req.ParentId,
		TopicId:     req.TopicId,
		Status:      req.Status,
		StartTime:   req.StartTime,
		EndTime:     req.EndTime,
		OrderBy:     orderBys,
		FilterBy:    filterBys,
		WithMeta:    req.WithMeta,
		WithMedia:   req.WithMedia,
		WithCard:    req.WithCard,
		WithTag:     req.WithTag,
		SkipContent: req.SkipContent,
	})
	if err != nil {
		return nil, err
	}

	resp := &types.ForumPostListResp{
		BaseDataInfo: types.BaseDataInfo{
			Success: true,
			Msg:     l.svcCtx.Trans.Trans(l.ctx, i18n.Success),
		},
		Data: types.ForumPostListInfo{
			BaseListInfo: types.BaseListInfo{
				Current:  page,
				PageSize: pageSize,
				Total:    data.GetTotal(),
			},
			StatusStatisticMap: data.StatusStatisticMap,
		},
	}

	var parentMap map[uint64]*types.KBEntryInfo
	if req.WithParent != nil && *req.WithParent > 0 {
		parentMap = make(map[uint64]*types.KBEntryInfo)
		var pids []string
		for _, v := range data.List {
			if v.ParentId != nil && *v.ParentId > 0 {
				pids = append(pids, strconv.FormatUint(*v.ParentId, 10))
			}

			if len(pids) > 0 {
				data, err := l.svcCtx.BlogRpc.BackendGetKBPostList(l.ctx, &blogclient.TmpKBPostListReq{
					Ids:      pointy.GetPointer(strings.Join(pids, ",")),
					WithMeta: req.WithMeta,
				})
				if err != nil {
					return nil, err
				}

				for _, v := range data.List {
					if v.Id == nil || *v.Id == 0 {
						continue
					}

					var media []*types.MediaInfo
					if len(v.Media) > 0 {
						for _, m := range v.Media {
							var url string
							if m.Url != nil && len(*m.Url) > 0 {
								url = *m.Url
							}
							if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
								url = *m.Uri
							}
							filename, mimeType, metaData := utils.ParseMetaData(m.MetaData)
							media = append(media, &types.MediaInfo{
								Uid:       m.Uid,
								Id:        m.Id,
								Thumbnail: m.Thumbnail,
								Order:     m.Order,
								Url:       pointy.GetPointer(url),
								Name:      pointy.GetPointer(filename),
								MimeType:  pointy.GetPointer(mimeType),
								AltText:   m.AltText,
								MetaData:  pointy.GetPointer(metaData),
							})
						}
					}

					parentMap[*v.Id] = &types.KBEntryInfo{
						Title: v.Title,
						Slug:  v.Slug,
						Media: media,
					}
				}
			}
		}
	}

	for _, v := range data.List {
		var meta []*types.MetaInfo
		var media []*types.MediaInfo
		var cards []*types.PostCardInfo
		var tags []*types.ForumTermInfo
		var parent *types.KBEntryInfo

		if len(v.Meta) > 0 {
			for _, m := range v.Meta {
				if m.Key != nil && m.Value != nil {
					switch *m.Key {
					case "photoCount":
					default:
						meta = append(meta, &types.MetaInfo{
							Id:    m.Id,
							Key:   m.Key,
							Value: m.Value,
						})
					}
				}
			}
		}

		if len(v.Media) > 0 {
			for _, m := range v.Media {
				var url string
				if m.Url != nil && len(*m.Url) > 0 {
					url = *m.Url
				}
				if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
					url = *m.Uri
				}
				filename, mimeType, metaData := utils.ParseMetaData(m.MetaData)
				media = append(media, &types.MediaInfo{
					Uid:       m.Uid,
					Id:        m.Id,
					Thumbnail: m.Thumbnail,
					Order:     m.Order,
					Url:       pointy.GetPointer(url),
					Name:      pointy.GetPointer(filename),
					MimeType:  pointy.GetPointer(mimeType),
					AltText:   m.AltText,
					MetaData:  pointy.GetPointer(metaData),
				})
			}
		}

		if len(v.Cards) > 0 {
			for _, m := range v.Cards {
				cards = append(cards, &types.PostCardInfo{
					Uid:      m.Uid,
					Id:       m.Id,
					Type:     m.Type,
					LinkUrl:  m.LinkUrl,
					Title:    m.Title,
					PicUrl:   m.PicUrl,
					Subtitle: m.Subtitle,
					Label:    m.Label,
					Price:    m.Price,
				})
			}
		}

		if len(v.Tags) > 0 {
			for _, m := range v.Tags {
				tags = append(tags, &types.ForumTermInfo{
					BaseIDInfo: types.BaseIDInfo{
						Id: m.Id,
					},
					Name: m.Name,
					Slug: m.Slug,
				})
			}
		}

		var author *types.ForumAuthorInfo
		if req.WithAuthor != nil && *req.WithAuthor > 0 {
			author = &types.ForumAuthorInfo{
				Id:       v.AuthorId,
				Nickname: v.AuthorNickname,
				Avatar:   v.AuthorAvatar,
			}
		}

		if v.ParentId != nil && *v.ParentId > 0 && parentMap != nil {
			if pv, ok := parentMap[*v.ParentId]; ok {
				parent = pv
			}
		}

		option := utils.GetAuditOptionByStatus(v.Status)
		resp.Data.List = append(resp.Data.List, &types.ForumPostInfo{
			BaseIDInfo: types.BaseIDInfo{
				Id:         v.Id,
				CreatedAt:  v.CreatedAt,
				UpdatedAt:  v.UpdatedAt,
				DeletedAt:  v.DeletedAt,
				CanAccept:  option.CanAccept,
				CanReject:  option.CanReject,
				CanRemove:  option.CanRemove,
				CanRestore: option.CanRestore,
			},
			Title:         v.PostTitle,
			Excerpt:       v.PostExcerpt,
			AuthorId:      v.AuthorId,
			Status:        v.Status,
			CommentStatus: v.CommentStatus,
			Sort:          v.Sort,
			Sticky:        v.Sticky,
			CanStick:      option.CanStick,
			TopicId:       v.TopicId,
			ParentId:      v.ParentId,
			PhotoCount:    v.PhotoCount,
			CreatedBy:     v.CreatedBy,
			PublicDate:    v.PublicDate,
			CanSubmit:     option.CanSubmit,
			Parent:        parent,
			Meta:          meta,
			Media:         media,
			Card:          cards,
			Author:        author,
			Tag:           tags,
		})
	}

	return resp, nil
}
